iT邦幫忙

2025 iThome 鐵人賽

DAY 24
0
自我挑戰組

30天用Python打造你的數位金融實力:從零開始的FinTech入門筆記系列 第 24

健康保險 × 風險因子:用 BMI 做保費等級模擬

  • 分享至 

  • xImage
  •  

今日目標

  • 認識 BMI 與常見分級(台灣常用分級)
  • 用「年齡帶 → 基礎保費」「BMI 分級 → 風險加成」「是否吸菸 → 額外加成」做一個保費估算器
  • 一鍵輸出多位被保人的報價列表 CSV

溫馨提醒:這是教學用的簡化版,並非真實商品定價或醫療建議。實務需要大量統計資料、法規與精算檢核。

BMI 是什麼?

  • 公式:BMI = 體重(kg) ÷(身高(公尺))²
  • 台灣常見分級(示意):
    • < 18.5:體重過輕
    • 18.5–24:正常
    • 24–27:過重
    • 27–30:肥胖 I
    • 30–35:肥胖 II
    • ≥ 35:肥胖 III

Python 小實作

import csv
from math import pow

# 1) 基礎保費:按年齡帶(示意金額,單位:TWD/年)
AGE_BASE = [
    (18, 29, 6000),
    (30, 39, 7200),
    (40, 49, 9000),
    (50, 59, 12000),
    (60, 65, 16000)
]

# 2) BMI 分級與對應風險加成(僅示意)
#    例如 0.15 代表 +15%
BMI_BANDS = [
    ("體重過輕",  None, 18.5, 0.10),
    ("正常",      18.5, 24.0, 0.00),
    ("過重",      24.0, 27.0, 0.15),
    ("肥胖 I",    27.0, 30.0, 0.30),
    ("肥胖 II",   30.0, 35.0, 0.60),
    ("肥胖 III",  35.0, None, 1.00),
]

SMOKER_LOADING = 0.40  # 吸菸者 +40%(示意)

def bmi_value(height_cm: float, weight_kg: float) -> float:
    h_m = height_cm / 100.0
    return weight_kg / pow(h_m, 2)

def bmi_class_and_loading(bmi: float):
    for name, lo, hi, ld in BMI_BANDS:
        if (lo is None or bmi >= lo) and (hi is None or bmi < hi):
            return name, ld
    return "未定義", 0.0

def base_premium_by_age(age: int) -> int:
    for lo, hi, base in AGE_BASE:
        if lo <= age <= hi:
            return base
    # 若超出範圍,給予簡單外推(示意)
    if age < AGE_BASE[0][0]:
        return AGE_BASE[0][2]
    return int(AGE_BASE[-1][2] * 1.3)

def quote_premium(profile: dict):
    age = profile["age"]
    h = profile["height_cm"]
    w = profile["weight_kg"]
    smoker = profile.get("smoker", False)

    bmi = round(bmi_value(h, w), 1)
    bmi_cls, bmi_ld = bmi_class_and_loading(bmi)
    base = base_premium_by_age(age)

    total_loading = bmi_ld + (SMOKER_LOADING if smoker else 0.0)
    premium = round(base * (1 + total_loading))

    breakdown = {
        "name": profile.get("name", ""),
        "age": age,
        "height_cm": h,
        "weight_kg": w,
        "smoker": "是" if smoker else "否",
        "BMI": bmi,
        "BMI分級": bmi_cls,
        "基礎保費": base,
        "風險加成(%)": f"{int(total_loading*100)}%",
        "年保費_估": premium
    }
    return breakdown

# 3) 測試三位被保人(你可以自行修改)
people = [
    {"name": "Alice", "age": 29, "height_cm": 165, "weight_kg": 56, "smoker": False},  # 正常
    {"name": "Bob",   "age": 43, "height_cm": 175, "weight_kg": 88, "smoker": False},  # 過重/肥胖I邊緣
    {"name": "Carol", "age": 37, "height_cm": 160, "weight_kg": 95, "smoker": True},   # 肥胖II + 吸菸
]

rows = [quote_premium(p) for p in people]

# 列印結果
print("=== BMI 保費模擬(示意)===")
for r in rows:
    print(f"{r['name']:>5}|年齡:{r['age']:>2} |BMI:{r['BMI']:>4}({r['BMI分級']})"
          f"|基礎保費:{r['基礎保費']:>6}|加成:{r['風險加成(%)']:>4}|估算年保費:{r['年保費_估']:>6}|吸菸:{r['smoker']}")

# 4) 輸出 CSV,方便後續視覺化或做報告
with open("premium_quote.csv", "w", newline="", encoding="utf-8") as f:
    writer = csv.DictWriter(f, fieldnames=list(rows[0].keys()))
    writer.writeheader()
    writer.writerows(rows)

print("\n✅ 已輸出報價列表:premium_quote.csv")

會看到什麼(示意解讀)

  • Alice(正常 BMI):幾乎不加價,保費接近該年齡帶的基礎保費。
  • Bob(過重/肥胖 I 邊緣):依 BMI 類別加上 15%~30% 左右的加成。
  • Carol(肥胖 II+吸菸):BMI 加成 + 吸菸加成,保費提升幅度最大。

為什麼這樣設計?

  • 保險定價的直覺:風險越高(例如肥胖合併吸菸),理賠期望值越高 → 保費加成越多。
  • 透明可調:把規則寫在程式頂部,你就能快速做 What-if:調整 BMI 門檻或加成、調整年齡帶。
  • 實戰連結:這種「規則表 → 報價引擎」的做法,正是很多保險公司在 PoC 階段會做的 MVP。

延伸練習

  1. 加「運動習慣」折扣:例如每週運動 ≥ 3 次,−5%。
  2. 把年保費拆成月繳:加入分期費用或手續費。
  3. 加入風險上限:對於「肥胖 III + 吸菸」,保費上限不超過基礎保費的 2.2 倍(示意)。
  4. 與 Day23 串接:把今日的加成轉成「事故頻率/嚴重度」的不同參數,做更完整的模擬。

上一篇
保險理賠模擬器:免賠額、共付比、理賠上限怎麼影響保費?
下一篇
用 Python 每週產生消費摘要並自動寄信
系列文
30天用Python打造你的數位金融實力:從零開始的FinTech入門筆記29
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言